package com.xframework.security.service;

import java.util.List;
import java.util.ArrayList;
import java.util.Date;

import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.xframework.Base;
import com.xframework.annotation.NotKey;
import com.xframework.exception.BusinessException;
import com.xframework.exception.ExceptionCode;
import com.xframework.redis.XRedisTemplate;
import com.xframework.service.BaseService;
import com.xframework.security.api.SecurityRpcService;
import com.xframework.security.dao.SecurityDao;
import com.xframework.security.manage.SecurityManage;
import com.xframework.security.model.*;
import com.xframework.security.util.Constant;
import com.xframework.security.util.RSAUtil;

@DubboService
@Component
public class SecurityService extends BaseService implements SecurityRpcService {

    @Autowired
    private SecurityManage securityManage;

    @Autowired
    private SecurityDao securityDao;

    public SecurityService() {

    }

    @Override
    public SecurityAccount selectAccount(Account account, String applicationId, @NotKey String accountIp) {
        try {
            return securityManage.selectAccount(account, applicationId, accountIp);
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    @Override
    public boolean validateAccountPassword(String accountPasswordExpress, String accountPasswordEncryption) {
        try {
            return RSAUtil.verify(accountPasswordExpress, accountPasswordEncryption);
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    /**
     * @param account Account
     * @return Account
     */
    @Override
    public Account insertAccount(Account account) {
        try {
            String password = account.getAccountPassword();
            if (password != null) {
                account.setAccountPassword(RSAUtil.encryptByPublicKey(password));
            }
            securityManage.insertAccount(account);
            return account;
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    /**
     * @param account Account
     */
    @Override
    public int updateAccount(Account account) {
        try {
            return securityManage.updateAccount(account);
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    @Override
    public int updateAccountByAccount(Account accountSet, Account accountWhere) {
        try {
            String date = getCurrentDate(0, Base.YYYY_MM_DD_HH_MM_SS);
            String password = accountSet.getAccountPassword();
            if (password != null) {
                accountSet.setAccountPassword(RSAUtil.encryptByPublicKey(password));
            }
            accountSet.setAccountModifyTime(date);
            return this.update(accountSet, accountWhere);
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    @Override
    public int deleteAccount(Account account) {
        try {
            return securityManage.deleteAccount(account);
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    /**
     * @param account Account
     * @return int
     */
    @Override
    public int selectAccountNum(Account account) {
        try {
            return securityDao.selectAccountNum(account);
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    @Override
    public List<Account> selectAccountList(Account account) {
        try {
            return securityDao.selectAccountList(account);
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    @Override
    public List<Account> selectRoleAccountList(AccountRole accountRole) {
        try {
            return securityDao.selectRoleAccountList(accountRole);
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    @Override
    public void insertAccountProperty(Property property) {
        try {
            String date = getCurrentDate(0, Base.YYYY_MM_DD_HH_MM_SS);
            property.setPropertyCreateTime(date);
            property.setPropertyModifyTime(date);
            this.insert(property);
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    @Override
    public void updateAccountProperty(Property property) {
        try {
            String date = getCurrentDate(0, Base.YYYY_MM_DD_HH_MM_SS);
            if (this.isString(property.getAccountId()) && this.isString(property.getPropertyKey())) {
                property.setPropertyModifyTime(date);
                this.update(property);
            }
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    @Override
    public void deleteAccountProperty(Property property) {
        try {
            if (this.isString(property.getAccountId()) && this.isString(property.getPropertyKey())) {
                this.delete(property);
            }
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    @Override
    public List<Property> selectAccountPropertyList(Property property) {
        try {
            return securityDao.selectAccountPropertyList(property);
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    @Override
    public void insertAccountRole(AccountRole accountRole, List<Role> roleList) {
        try {
            securityManage.insertAccountRole(accountRole, roleList);
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    @Override
    public List<Role> selectAccountRoleList(AccountRole accountRole) {
        try {
            return securityDao.selectAccountRoleList(accountRole);
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    /**
     * 新建应用
     *
     * @param application Application
     * @return Application
     */
    @Override
    public Application insertApplication(Application application) {
        try {
            String date = getCurrentDate(0, Base.YYYY_MM_DD_HH_MM_SS);
            application.setApplicationCreateTime(date);
            application.setApplicationModifyTime(date);
            return this.insert(application);
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    /**
     * 更新应用
     *
     * @param application Application
     */
    @Override
    public void updateApplication(Application application) {
        try {
            if (this.isString(application.getApplicationId())) {
                String date = getCurrentDate(0, Base.YYYY_MM_DD_HH_MM_SS);
                application.setApplicationModifyTime(date);
                this.update(application);
            }
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    @Override
    public void deleteApplication(Application application) {
        try {
            if (this.isString(application.getApplicationId())) {
                this.delete(application);
            }
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    /**
     * 查询系统应用
     *
     * @return List
     */
    @Override
    public List<Application> selectApplicationList(Application application) {
        try {
            return securityDao.selectApplicationList(application);
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    /**
     * 查询系统应用
     *
     * @param application
     * @return
     */
    @Override
    public int selectApplicationNum(Application application) {
        try {
            return securityDao.selectApplicationNum(application);
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    /**
     * 新建资源
     *
     * @param resource Resource
     * @return Resource
     */
    @Override
    public Resource insertResource(Resource resource) {
        try {
            String date = getCurrentDate(0, Base.YYYY_MM_DD_HH_MM_SS);
            resource.setResourceCreateTime(date);
            resource.setResourceModifyTime(date);
            return this.insert(resource);
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    /**
     * 更新资源
     *
     * @param resource Resource
     */
    @Override
    public int updateResource(Resource resource) {
        try {
            if (this.isString(resource.getResourceId())) {
                String date = getCurrentDate(0, Base.YYYY_MM_DD_HH_MM_SS);
                resource.setResourceModifyTime(date);
                return this.update(resource);
            } else {
                return 0;
            }
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    @Override
    public void deleteResource(Resource resource) {
        try {
            if (this.isString(resource.getResourceId())) {
                this.delete(resource);
            }
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    @Override
    public List<Resource> selectResourceList(Resource resource) {
        try {
            return securityDao.selectResourceList(resource);
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    @Override
    public ResourceType insertResourceType(ResourceType resourceType) {
        try {
            return this.insert(resourceType);
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    @Override
    public int updateResourceType(ResourceType resourceType) {
        try {
            return this.update(resourceType);
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    @Override
    public void deleteResourceType(ResourceType resourceType) {
        try {
            this.delete(resourceType);
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    @Override
    public List<ResourceType> selectResourceTypeList(ResourceType resourceType) {
        try {
            return securityDao.selectResourceTypeList(resourceType);
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    /**
     * 返回所有的资源放在ApplicationList里
     *
     * @return List
     */
    @Override
    public List<Application> selectApplicationResourceList(Application application) {
        try {
            List<Resource> resourceList = securityDao.selectResourceList(new Resource());
            resourceList = securityManage.treeResourceList(resourceList);
            List<Application> applicationList = securityDao.selectApplicationList(application);
            for (Application a : applicationList) {
                List<Resource> menuList = new ArrayList<Resource>();
                for (Resource menu : resourceList) {
                    if (menu.getResourceParentId().equals(Constant.MENU_INIT_ID)) {
                        if (a.getApplicationId().equals(menu.getApplicationId())) {
                            menuList.add(menu);
                        }
                    }
                }
                if (menuList.size() > 0) {
                    a.setResourceList(menuList);
                }
            }
            return applicationList;
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    /**
     * 新建角色
     *
     * @param role Role
     * @return Role
     */
    @Override
    public Role insertRole(Role role) {
        try {
            return securityManage.insertRole(role);
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    @Override
    public ThirdRole insertThirdRole(ThirdRole thirdRole) {
        try {
            return securityManage.insertThirdRole(thirdRole);
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0000, e);
        }
    }

    /**
     * 更新角色
     *
     * @param role Role
     */
    @Override
    public void updateRole(Role role) {
        try {
            securityManage.updateRole(role);
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    @Override
    public void deleteRole(Role role) {
        try {
            securityManage.deleteRole(role);
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    /**
     * 查询角色
     *
     * @return List
     */
    @Override
    public List<Role> selectRoleList(Role role) {
        try {
            return securityDao.selectRoleList(role);
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    @Override
    public List<Role> selectThirdRoleList(ThirdRole thirdRole) {
        try {
            return securityDao.selectThirdRoleList(thirdRole);
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    /**
     * 查询角色
     *
     * @param role
     * @return
     */
    @Override
    public int selectRoleNum(Role role) {
        try {
            return securityDao.selectRoleNum(role);
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    @Override
    public int selectThirdRoleNum(ThirdRole thirdRole) {
        try {
            return securityDao.selectThirdRoleNum(thirdRole);
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    @Override
    public void insertRoleResource(RoleResource roleResource, String resourceIds) {
        try {
            securityManage.insertRoleResource(roleResource, resourceIds);
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    @Override
    public List<Resource> selectRoleResourceList(RoleResource roleResource) {
        try {
            return securityDao.selectRoleResourceList(roleResource);
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    @Override
    public List<Resource> selectAccountResourceList(SecurityAccount securityAccount) {
        try {
            return securityDao.selectResourceByAccountApplication(securityAccount);
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    public String genRandom(String mobile, int length, int expireSencods) {
        try {
            String random = Base.getUid(length);
            XRedisTemplate.setString(Constant.SECURITY_RANDOM_ + mobile, random, expireSencods);
            return random;
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

    public boolean verifyRandom(String mobile, String random) {
        try {
            boolean flag = Boolean.FALSE;
            String redisRandom = XRedisTemplate.get(Constant.SECURITY_RANDOM_ + mobile);
            if (random.equals(redisRandom)) {
                flag = Boolean.TRUE;
            }
            return flag;
        } catch (Exception e) {
            throw new BusinessException(ExceptionCode.EXCEPTION_CODE0001, e);
        }
    }

}
